#include "dfu_update.h"

struct DFU_UPDATE dfu;

uint8_t update_frames[SZ_16];
uint8_t update_status[SZ_16];
uint8_t update_frames_stats[SZ_16][SZ_6];
uint8_t update_frames_trays[SZ_16][SZ_6];
uint8_t update_trays_stats[SZ_16][SZ_6];

uint8_t data_packet[70][520];

// 报错
static void errorReport(unsigned char err_info)
{

}

// 发送命令，参数为 socket号 、 命令标示 和 命令参数
static void sendCommand(int sock_fd, const char* cmd, const char* info)
{
    char buf[BUF_SIZE] = {0};

    strcpy(buf, cmd);
    strcat(buf, info);
    strcat(buf, "\r\n");
    if (send(sock_fd, buf, strlen(buf), 0) < 0){
        errorReport(1);
	}
}

// 控制连接获取服务器应答，返回应答码
static int getReplyCode(int sockfd)
{
    int r_code, bytes;
    char buf[BUF_SIZE] = {0}, nbuf[5] = {0};

    if ((bytes = read(sockfd, buf, BUF_SIZE - 2)) > 0) {
        r_code = atoi(buf);
        buf[bytes] = '\0';
    }else{
        return -1;
	}

    if (buf[3] == '-') {
        char* newline = strchr(buf, '\n');
        if (*(newline+1) == '\0') {
            while ((bytes = read(sockfd, buf, BUF_SIZE - 2)) > 0) {
                buf[bytes] = '\0';
                if (atoi(buf) == r_code)
                    break;
            }
        }
    }

    if (r_code == PASV_MODE){
        char* begin = strrchr(buf, ',')+1;
        char* end = strrchr(buf, ')');
        strncpy(nbuf, begin, end - begin);
        nbuf[end-begin] = '\0';
        data_port = atoi(nbuf);
        buf[begin-1-buf] = '\0';
        end = begin - 1;
        begin = strrchr(buf, ',')+1;
        strncpy(nbuf, begin, end - begin);
        nbuf[end-begin] = '\0';
        data_port += 256 * atoi(nbuf);
    }

    return r_code;
}

// 连接到服务器，参数为 IP地址 和 端口号，返回是否连接成功的编号
static int connectToHost(void)
{
    int sockfd = 0, port = 0;

    server.sin_family = AF_INET;
    server.sin_port   = htons(dfu.port);
	server.sin_addr.s_addr = dfu.serverip[3]<<24 | dfu.serverip[2]<<16 | dfu.serverip[1]<<8 | dfu.serverip[0];

    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        errorReport(3);
    if(connect(sockfd, (struct sockaddr*)&server, sizeof(server)) < 0)
        errorReport(4);
    
	return sockfd;
}

// 用户登录
static int userLogin(int sockfd)
{
    sendCommand(sockfd, "USER ", user);
    if(getReplyCode(sockfd) == NEED_PASSWORD)
	{
        sendCommand(sockfd, "PASS ", pass);
        if(getReplyCode(sockfd) != LOGIN_SUCS)
		{ //login success!
            return -1;
        }else{
            return 0;
        }
    }else{
        return -1;
    }
}

// 下载服务器的一个文件
static int cmd_get(int fd, char* cmd,unsigned char *src)
{
    int i = 0, bytes = 0;
	char filename[SZ_256];
	unsigned char buf[520];
	unsigned char packetnums = 0x0;

	data_port = 0;
	data_sock = -1;
    sendCommand(fd, "PASV", "");
    if (getReplyCode(fd) != PASV_MODE){
        return 0;
    }

    server.sin_port = htons(data_port);
    if((data_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        errorReport(5);
	}

    if(connect(data_sock, (struct sockaddr*)&server, sizeof(server)) < 0){
        errorReport(6);
	}

    sendCommand(fd, "TYPE ", "I");
    getReplyCode(fd);

	if(src[347] == 0x01){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "44b0");
	    getReplyCode(fd);	
	}else if(src[347] == 0x02){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "146");
	    getReplyCode(fd);
	}else if(src[347] == 0x03){
		sendCommand(fd, "CWD ", "ODF");
	    getReplyCode(fd);
	    sendCommand(fd, "CWD ", "410");
	    getReplyCode(fd);
	}

	strcpy(filename,cmd);
    sendCommand(fd, "RETR ",filename);
	if(getReplyCode(fd) != DOWN_READY){
        errorReport(7);
        close(fd);
        return 0;
	}

	if(src[347] == 0x01){
		return 0;
	}

	memset(buf,0xff,sizeof(buf));
	data_packet_num = 0;
	packetnums = 0;
	for(i = 0; i < 60;i++){
		memset(&data_packet[i],0xff,520);
	}

    while((bytes = read(data_sock, buf, BUF_SIZE)) > 0){
		memcpy(&data_packet[packetnums][0],buf,BUF_SIZE);	
		packetnums += 1;	
		memset(buf,0xff,sizeof(buf));
		data_packet_num++;
		usleep(50000);
	}
	
    close(data_sock);
	
	return 0;
}

// 退出
static void cmd_quit(int fd)
{
    sendCommand(fd, "QUIT", "");
    if (getReplyCode(fd) == CONTROL_CLOSE)
	{

	}
}


static void split_filename(unsigned char *file,int len)
{
	int i = len,j = 0;
	char version[20];
	unsigned char idex = 0;

	for(;i > 0;i--){
		if(*(file+i) == 0x5c)
			break;
	}

	strncpy(&dfu.filename[0],&file[0] + i + 1,len-(i-1));
	strncpy(&version[0],&file[0] + i + 1,len-(i-1));
	newfilename[len-i+1] = '\0';

	idex = 0;
	for(j = 0;j < len-i+1;j++){
		if(version[j] == 0x5f){//5f:is symbol for "_"
			dfu.fversion[idex++] = version[j+1]-0x30;
			dfu.fversion[idex++] = version[j+2]-0x30;
		}
	}
}

/*
 *decription: 自己写的ftp客户端软件，适配于njpt2416主控板用
 *
 *
 */
int ftp(unsigned char *username, unsigned char *password, unsigned char* serverip, 
		unsigned char* serverport,unsigned char *filepath,unsigned char *src)
{
	int control_sockfd = 0;

	/* 清除ftp使用过程中需要登录是用到的:用户名，密码，下载的文件名，下载文件路径 */
	memset((void *)&dfu, 0x0, sizeof(struct DFU_UPDATE));

	/* 记录ftp使用过程中需要登录是用到的:用户名，密码，下载的文件名，下载文件路径 */
	strncpy(&dfu.username[0],&username[0]+1,*(username+0));
	strncpy(&dfu.password[0],&password[0]+1,*(passwd+0));
	strncpy(&dfu.filepath[0],&filepath[0]+2,filepath[0]<<8|filepath[1]);
	strncpy(&dfu.serverip[0],&serverip[0]+2,4);
	dfu.port = serverport[0]*100 + serverport[1];

	/* 从网管给出的数据中，提取出文件名,并记录本次升级文件的版本号 */
	split_filename(filepath,filepath[0]<<8|filepath[1]);
	
	/* 尝试连接远程的ftp服务器,建立命令传送通道 */
    server.sin_family = AF_INET;
    server.sin_port   = htons(dfu.port);
	server.sin_addr.s_addr = dfu.serverip[3]<<24 | dfu.serverip[2]<<16 | dfu.serverip[1]<<8 | dfu.serverip[0];
    if((control_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("Socket Error!\n");
		return FTP_ERROR;
	}

    if(connect(control_sockfd, (struct sockaddr*)&server, sizeof(server)) < 0){
		perror("Connect Error\n");
		return FTP_ERROR;
	}

    if(getReplyCode(control_sockfd) != SERVICE_READY){
		printf("FTP Server Service Not Ready! \n");
		return FTP_ERROR;
	}
	
	/* 连接上之后，尝试登入到远程的ftp服务器上 */ 
	for(;;){
	    sendCommand(control_sockfd, "USER ", &dfu.username[0]);
    	if(getReplyCode(control_sockfd) == NEED_PASSWORD)
		{
        	sendCommand(control_sockfd, "PASS ", &dfu.password[0]);
        	if(getReplyCode(control_sockfd) != LOGIN_SUCS){ 
        	    return -1;
        	}else{
        	    return 0;
        	}
    	}else{
    	    return -1;
    	}
	}
   
	/* 登录成功后，下载本次升级所需要的文件 */
	rc = cmd_get(control_sockfd, &dfu.filename, src);
	if(src[347] == 0x01){
		/* don't close control_sockfd,because we need transfer data before close */
		return rc;
	}

	/* 下载文件完成后，跟ftp服务器说声goodbye :) */
	cmd_quit(control_sockfd);
    close(control_sockfd);

	return 0;

}

